/*
  This file is part of 'Trivial chess'.

  'Trivial chess' is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  'Trivial chess' is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with 'Trivial chess'.  If not, see <http://www.gnu.org/licenses/>.
*/

/* SVN FILE: $Id$ */
/**
 * @author         $Author$
 * @version        $Rev$
 * @lastrevision   $Date$
 * @filesource     $URL$
 */

#ifndef CASTLINGAVAILABILITYABSTRACT_H_
#define CASTLINGAVAILABILITYABSTRACT_H_

#include "../MeAbstract.h"
#include "../IoAbstract.h"

template<class CastlingAvailability>
class CastlingAvailabilityAbstract
	: public MeAbstract<CastlingAvailability>
	, public IoAbstract<CastlingAvailability> {
public:
	bool whiteQueen() const;
	bool blackQueen() const;
	bool whiteKing() const;
	bool blackKing() const;

	template<class Color>
	bool queen(Color color) const {
		return color.isWhite()
				? this->me_c().whiteQueen()
				: this->me_c().blackQueen();
	}

	template<class Color>
	bool king(Color color) const {
		return color.isWhite()
				? this->me_c().whiteKing()
				: this->me_c().blackKing();
	}

	bool white() const {
		return this->me_c().whiteKing() || this->me_c().whiteQueen();
	}
	bool black() const  {
		return this->me_c().blackKing() || this->me_c().blackQueen();
	}

	void setWhiteQueen();
	void setBlackQueen();
	void setWhiteKing();
	void setBlackKing();

	void unsetWhiteQueen();
	void unsetBlackQueen();
	void unsetWhiteKing();
	void unsetBlackKing();

	template<class Color>
	void unset(Color color) {
		if ( color.isWhite() ) {
			this->me().unsetWhiteQueen();
			this->me().unsetWhiteKing();
		}
		else {
			this->me().unsetBlackQueen();
			this->me().unsetBlackKing();
		}
	}

	template<class Color>
	void unsetKing(Color color) {
		if ( color.isWhite() )
			this->me().unsetWhiteKing();
		else
			this->me().unsetBlackKing();
	}

	template<class Color>
	void unsetQueen(Color color) {
		if ( color.isWhite() )
			this->me().unsetWhiteQueen();
		else
			this->me().unsetBlackQueen();
	}

	bool operator==(const CastlingAvailability ca) const {
		return ca.whiteQueen() == this->me_c().whiteQueen()
				&& ca.blackQueen() == this->me_c().blackQueen()
				&& ca.blackKing() == this->me_c().blackKing()
				&& ca.whiteKing() == this->me_c().whiteKing();
	}

	void clear() {
		this->me().unsetWhiteKing();
		this->me().unsetWhiteQueen();
		this->me().unsetBlackKing();
		this->me().unsetBlackQueen();
	}

	std::string toStr() const {
		std::string ret = "";

		if ( this->me_c().whiteKing() )
			ret += 'K';
		if ( this->me_c().whiteQueen() )
			ret += 'Q';
		if ( this->me_c().blackKing() )
			ret += 'k';
		if ( this->me_c().blackQueen() )
			ret += 'q';

		if ( 0 == ret.length() )
			return "-";
		else
			return ret;
	}

	void fromStr(const std::string str) {

		this->me().clear();
		std::string::const_iterator i;

		if ( "-" == str )
			return;

		for ( i = str.begin(); i != str.end(); ++i ) {
			if ( 'K' == *i )
				this->me().setWhiteKing();
			else if ( 'Q' == *i )
				this->me().setWhiteQueen();
			else if ( 'k' == *i )
				this->me().setBlackKing();
			else if ( 'q' == *i )
				this->me().setBlackQueen();
		}
	}
};

#endif /* CASTLINGAVAILABILITYABSTRACT_H_ */
